package com.example.app.service.impl;

import com.example.app.constants.StateConstants;
import com.example.app.dao.PatientRepository;
import com.example.app.dao.ReservationRepository;
import com.example.app.dao.VisitRecordRepository;
import com.example.app.dao.mongdb.MongoOrganRepository;
import com.example.app.dao.mongdb.MongoUserRepository;
import com.example.app.model.Organ;
import com.example.app.model.Patient;
import com.example.app.model.Reservation;
import com.example.app.model.SystemConfig;
import com.example.app.model.User;
import com.example.app.model.VisitRecord;
import com.example.app.service.ReservationService;
import com.example.app.service.SystemConfigService;
import com.example.app.service.UserService;
import com.example.app.utils.BusinessUtil;
import org.beetl.sql.core.SQLManager;
import org.beetl.sql.core.SQLReady;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.transaction.Transactional;
import java.text.ParseException;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * Created by wangtao on 2018/5/17.
 */
@Service
public class ReservationServiceImpl implements ReservationService {

    @PersistenceContext
    EntityManager em;

    @Autowired
    SQLManager sqlManager;

    @Autowired
    private ReservationRepository reservationRepository;

    @Autowired
    private VisitRecordRepository visitRecordRepository;

    @Autowired
    private PatientRepository patientRepository;

    @Autowired
    private MongoUserRepository mongoUserRepository;

    @Autowired
    private MongoOrganRepository mongoOrganRepository;

    @Autowired
    private SystemConfigService systemConfigService;

    @Autowired
    private UserService userService;

    @Override
    public List<Reservation> findByAppointment(Long patientId, String startDate, String endDate) {
        StringBuilder sql = new StringBuilder("select * from business_reservation");
        sql.append(" where patient_id = " + patientId);
        sql.append(" and status <> " + StateConstants.RESERVATION_STATUS_CANCEL);
        sql.append(" and appointment BETWEEN '" + startDate + " 00:00:00'");
        sql.append(" and '" + endDate + " 23:59:59'");
        return sqlManager.execute(new SQLReady(sql.toString()), Reservation.class);
    }

    @Override
    @Transactional
    public void doGenerateAppointment(Patient patient, Organ organ, User doctor, User nurse, Date appointment, String remark) {
        // 保存预约记录
        Reservation reservation = new Reservation();
        reservation.setPatientId(patient.getId());
        reservation.setPatientName(patient.getName());
        reservation.setMedicalNumber(patient.getMedicalNumber());
        reservation.setStatus(StateConstants.RESERVATION_STATUS_NEW);
        reservation.setType(StateConstants.RESERVATION_TYPE_OLD);
        reservation.setRecordType(StateConstants.RESERVATION_RECORD_TYPE_RESERVATION);
        reservation.setRemind(StateConstants.RESERVATION_REMIND_WECHAT);
        reservation.setProcess(StateConstants.RESERVATION_PROCESS_ARRIVAL);
        reservation.setDoctorId(doctor.getId());
        reservation.setDoctorName(doctor.getUsername());
        reservation.setNurseId(nurse.getId());
        reservation.setNurseName(nurse.getUsername());
        reservation.setAppointment(appointment);
        reservation.setNote(remark);
        reservation.setAccountId(patient.getAccountId());
        reservation.setUserId(patient.getUserId());
        reservation.setOrganId(organ.getId());
        reservation.setOrganName(organ.getOrganName());
        BusinessUtil.appendRecord(reservation);
        reservationRepository.save(reservation);
        // 生成接诊记录
        VisitRecord visitRecord = new VisitRecord();
        visitRecord.setPatientId(patient.getId());
        visitRecord.setDoctorId(reservation.getDoctorId());
        visitRecord.setNurseId(reservation.getNurseId());
        visitRecord.setAppointment(reservation.getAppointment());
        visitRecord.setType(reservation.getType());
        visitRecord.setAccountId(reservation.getAccountId());
        visitRecord.setUserId(reservation.getUserId());
        visitRecord.setOrganId(reservation.getOrganId());
        visitRecord.setOrganName(reservation.getOrganName());
        BusinessUtil.appendRecord(visitRecord);
        visitRecordRepository.save(visitRecord);
    }

    public boolean checkAppointment(Long patientId, String apptTime) {
        boolean ck = true;
        String ymd = apptTime.substring(0, apptTime.lastIndexOf(" "));
        StringBuilder sql = new StringBuilder("select count(1) as count from business_visit_record");
        sql.append(" where patient_id = " + patientId);
        sql.append(" and DATE_FORMAT(appointment,'%Y-%m-%d') = '" + ymd + "'");
        List<Map> resultMap = sqlManager.execute(new SQLReady(sql.toString()), Map.class);
        if (!resultMap.isEmpty() && resultMap.size() > 0) {
            Map map = resultMap.get(0);
            int count = Integer.parseInt(map.get("count").toString());
            if(count > 0){
                ck = false;
            }
        }
        return ck;
    }

    @Override
    public boolean doCheckDoctor(Long doctorId, String datetime, SystemConfig config) throws ParseException {
        boolean check = true;
        StringBuilder sql = new StringBuilder("select count(1) as count from business_visit_record");
        sql.append(" where doctor_id = " + doctorId);
        sql.append(" and appointment = '" + datetime + "'");
        sql.append(" and type = " + StateConstants.RESERVATION_TYPE_OLD);
        List<Map> list = sqlManager.execute(new SQLReady(sql.toString()), Map.class);
        // 医生在当前预约时间已接待复诊数量
        int n1 = Integer.parseInt(list.get(0).get("count").toString());
        // 医生限制接待复诊数量
        if(config.getDoctorReceptionOld() != null){
            int n2 = config.getDoctorReceptionOld().intValue();
            if(n1 >= n2){
                check = false;
            }
        }
        return check;
    }

    @Override
    public boolean doCheckNurse(Long nurseId, String datetime, SystemConfig config) throws ParseException {
        boolean check = true;
        StringBuilder sql = new StringBuilder("select count(1) as count from business_visit_record");
        sql.append(" where nurse_id = " + nurseId);
        sql.append(" and appointment = '" + datetime + "'");
        sql.append(" and type = " + StateConstants.RESERVATION_TYPE_OLD);
        List<Map> list = sqlManager.execute(new SQLReady(sql.toString()), Map.class);
        // 护士在当前预约时间已接待复诊数量
        int n1 = Integer.parseInt(list.get(0).get("count").toString());
        // 护士限制接待复诊数量
        if(config.getNurseReceptionOld() != null){
            int n2 = config.getNurseReceptionOld().intValue();
            if(n1 >= n2){
                check = false;
            }
        }
        return check;
    }

    @Override
    public boolean checkAppointment(Long patientId, String startTime, String endTime) {
        boolean check = true;
        StringBuilder sql = new StringBuilder("select count(1) as count from business_visit_record");
        sql.append(" where patient_id = " + patientId);
        sql.append(" and appointment between '" + startTime + "' and '" + endTime + "'");
        List<Map> list = sqlManager.execute(new SQLReady(sql.toString()), Map.class);
        int n1 = Integer.parseInt(list.get(0).get("count").toString());
        if(n1 > 0){
            check = false;
        }
        return check;
    }
}
